import type {
  AxiosInterceptorManager,
  AxiosRequestConfig,
  AxiosResponse,
  AxiosResponseHeaders,
  AxiosResponseTransformer,
  InternalAxiosRequestConfig
} from 'axios'
import axios, { AxiosError } from 'axios'
const processEnvDetail = process.env
  .processEnvDetail as Window['processEnvDetail']

export enum YmResponseCode {
  normal = '200',
  /**
   * @desc 服务器请求异常
   */
  serverException = '500',
  /**
   * @desc 没有访问权限
   */
  noRoot = '403',

  /**
   * @desc 没有登录信息
   *
   */
  noLogin = '5002',
  /**
   * @desc 暂未定义的错误
   */
  unknown = '0'
}

export interface YmResponse<T = undefined> {
  code: YmResponseCode // 错误类型
  data: T
  msg?: string
}

export interface YmRequest<
  ConfExpand extends InternalAxiosRequestConfig = InternalAxiosRequestConfig
> {
  <R = unknown, D = unknown>(
    config: Omit<ConfExpand, keyof InternalAxiosRequestConfig> &
      AxiosRequestConfig<D>
  ): Promise<YmResponse<R>>
  <R = unknown, D = unknown>(
    url: string,
    config?: Omit<ConfExpand, keyof InternalAxiosRequestConfig> &
      AxiosRequestConfig<D>
  ): Promise<YmResponse<R>>
  // 设置一个data转换器
  setTransformResponse(
    fn: (
      this: ConfExpand,
      value: unknown,
      headers: AxiosResponseHeaders,
      status?: number
    ) => YmResponse
  ): () => void
  // 参数转换器目前是不需要的

  interceptors: {
    request: AxiosInterceptorManager<ConfExpand>
    response: AxiosInterceptorManager<
      Omit<AxiosResponse<YmResponse<unknown>>, 'config'> & {
        config: ConfExpand
      }
    >
  }
}

interface CoreConfig<ConfExpand extends InternalAxiosRequestConfig> {
  transformResponse: (
    this: Readonly<ConfExpand>,
    value: unknown,
    headers: AxiosResponseHeaders,
    status?: number
  ) => YmResponse<unknown>
}

function core<
  ConfExpand extends InternalAxiosRequestConfig = InternalAxiosRequestConfig
>(params: CoreConfig<ConfExpand>) {
  const request = axios.create({
    withCredentials: false,
    method: 'post',
    // 注:本地主应用和子应用不在同一个服务器上
    baseURL: processEnvDetail.BASE_API
      ? '//localhost:4003/devapi'
      : window.location.origin
  })

  if (Array.isArray(request.defaults.transformResponse)) {
    request.defaults.transformResponse.push(
      params.transformResponse as AxiosResponseTransformer
    )
  }
  if (Array.isArray(request.defaults.transformRequest)) {
    // 在所有interceptors.response之前执行处理response.data
    request.defaults.transformRequest.unshift(function (data) {
      if (this.method === 'post' && this.params) {
        if (typeof this.params === 'object') {
          for (const key in this.params) {
            if (
              this.params[key] === null ||
              this.params[key] === undefined ||
              this.params[key] === ''
            ) {
              delete this.params[key]
            }
          }
          const _data: URLSearchParams = new URLSearchParams(this.params)
          delete this.params
          return _data
        } else {
          return this.params
        }
      }
      return data
    })
  }

  const myRequset = (<R = unknown, D = unknown>(
    urlOrConfig: string | AxiosRequestConfig<D>,
    config?: AxiosRequestConfig<D>
  ) => {
    if (typeof urlOrConfig === 'string') {
      return request<unknown, YmResponse<R>, D>(urlOrConfig, config)
    } else {
      return request<unknown, YmResponse<R>, D>(urlOrConfig)
    }
  }) as YmRequest<ConfExpand>

  // ----第一个拦截器-----
  // 拦截并判断请求是否成功。最开始执行的
  request.interceptors.response.use((value) => {
    const { data } = value
    // console.log('--interceptors.response.1--value---:', value);
    if (data.code === YmResponseCode.normal) {
      return value
    } else {
      return Promise.reject(
        new AxiosError(data.msg, data.code, value.config, value.request, value)
      )
    }
  })

  myRequset.interceptors =
    request.interceptors as YmRequest<ConfExpand>['interceptors']

  const use = request.interceptors.response.use.bind(
    myRequset.interceptors.response
  ) as YmRequest<ConfExpand>['interceptors']['response']['use']

  // ----第二个拦截器----
  const buildIn = function buildIn() {
    // 做数据转换
    return use(
      (value: any) => {
        // console.log('--interceptors.response.2--value---:', value);
        try {
          const { data } = value
          return data as unknown as typeof value
        } catch (error) {
          /* empty */
        }
      },
      (err) => {
        // console.log('--interceptors.response.2--err---:', err);
        const { code, message } = err
        if (err.config?.responseAsSuc) {
          return { code, message } // return Promise.resolve({code, message })
        } else {
          return Promise.reject({ code, message })
        }
      }
    )
  }
  let buildInId = buildIn()

  // ----第三个拦截器(在入口index.tsx中设置)-----
  // 如果第三个拦截器已设置，就把拦截器三和二换一个顺序,先执行第三个拦截器【多个拦截器是依次执行而不是覆盖】
  myRequset.interceptors.response.use = function (...args) {
    const number = use(...args)
    myRequset.interceptors.response.eject(buildInId) //清除拦截器
    buildInId = buildIn()
    return number
  }

  myRequset.setTransformResponse = function (fn) {
    if (Array.isArray(request.defaults.transformResponse)) {
      request.defaults.transformResponse.push(fn as AxiosResponseTransformer)
    }
    return function () {
      if (Array.isArray(request.defaults.transformResponse)) {
        const index = request.defaults.transformResponse.indexOf(
          fn as AxiosResponseTransformer
        )
        if (index !== -1) {
          request.defaults.transformResponse.splice(index, 1)
        }
      }
    }
  }

  return myRequset
}

export { core }
export type { InternalAxiosRequestConfig }
